import os
import json
import uuid
import logging
import hashlib
from typing import Dict, List, Optional, Any, Union, Tuple
from pathlib import Path

from secure_config_manager.core.config_manager import SecureConfigManager
from secure_config_manager.core.keychain import SystemKeychain
from secure_config_manager.core.encryption import EnhancedAES256Encryptor
from secure_config_manager.core.metadata_manager import MetadataManager, ConfigMetadata

# 配置日志
logger = logging.getLogger(__name__)

class MultiConfigManager:
    """多文件配置管理器，扩展SecureConfigManager以支持多文件"""
    
    def __init__(self, base_dir: Optional[str] = None):
        """
        初始化多文件配置管理器
        
        Args:
            base_dir: 配置文件存储的基础目录，默认为当前目录
        """
        self.base_dir = base_dir or os.getcwd()
        self.config_dir = os.path.join(self.base_dir, "configs")
        self.metadata_manager = MetadataManager(self.base_dir)
        
        # 确保配置目录存在
        os.makedirs(self.config_dir, exist_ok=True)
    
    def create_config(self, 
                     file_name: str, 
                     description: str = "", 
                     tags: Optional[List[str]] = None, 
                     initial_data: Optional[Dict[str, Any]] = None) -> Tuple[bool, str]:
        """
        创建新的配置文件
        
        Args:
            file_name: 文件名称
            description: 文件描述
            tags: 标签列表
            initial_data: 初始配置数据
            
        Returns:
            Tuple[bool, str]: (是否成功, 文件ID或错误消息)
        """
        try:
            # 生成唯一文件ID
            file_id = str(uuid.uuid4())
            
            # 构建文件路径
            file_path = os.path.join(self.config_dir, file_name)
            
            # 检查文件是否已存在
            if os.path.exists(file_path):
                return False, f"文件已存在: {file_name}"
            
            # 创建配置管理器
            config_manager = SecureConfigManager(file_path)
            
            # 如果有初始数据，添加到配置中
            if initial_data:
                for section, data in initial_data.items():
                    config_manager.add_section(section, data)
            
            # 保存配置
            config_manager.save_config(config_manager.config)
            
            # 计算文件校验和
            checksum = self._calculate_checksum(file_path)
            
            # 创建并添加元数据
            metadata = ConfigMetadata(
                file_id=file_id,
                file_name=os.path.relpath(file_path, self.base_dir),
                description=description,
                tags=tags,
                checksum=checksum,
                key_id=SystemKeychain.get_key_from_environment()
            )
            
            if self.metadata_manager.add_config(metadata):
                logger.info(f"创建配置文件成功: {file_name} (ID: {file_id})")
                return True, file_id
            else:
                # 添加元数据失败，删除已创建的文件
                if os.path.exists(file_path):
                    os.remove(file_path)
                return False, "添加元数据失败"
                
        except Exception as e:
            logger.error(f"创建配置文件失败: {str(e)}")
            return False, str(e)
    
    def load_config(self, file_id: str) -> Optional[Dict[str, Any]]:
        """
        加载配置文件内容
        
        Args:
            file_id: 文件ID
            
        Returns:
            Optional[Dict[str, Any]]: 配置数据或None
        """
        try:
            # 获取元数据
            metadata = self.metadata_manager.get_config(file_id)
            if not metadata:
                logger.warning(f"配置文件ID不存在: {file_id}")
                return None
            
            # 构建文件路径
            file_path = os.path.join(self.base_dir, metadata.file_name)
            
            # 检查文件是否存在
            if not os.path.exists(file_path):
                logger.warning(f"配置文件不存在: {file_path}")
                return None
            
            # 加载配置
            config_manager = SecureConfigManager(file_path)
            return config_manager.config
            
        except Exception as e:
            logger.error(f"加载配置文件失败: {str(e)}")
            return None
    
    def save_config(self, file_id: str, config_data: Dict[str, Any]) -> bool:
        """
        保存配置文件内容
        
        Args:
            file_id: 文件ID
            config_data: 配置数据
            
        Returns:
            bool: 保存是否成功
        """
        try:
            # 获取元数据
            metadata = self.metadata_manager.get_config(file_id)
            if not metadata:
                logger.warning(f"配置文件ID不存在: {file_id}")
                return False
            
            # 构建文件路径
            file_path = os.path.join(self.base_dir, metadata.file_name)
            
            # 检查文件是否存在
            if not os.path.exists(file_path):
                logger.warning(f"配置文件不存在: {file_path}")
                return False
            
            # 保存配置
            config_manager = SecureConfigManager(file_path)
            config_manager.config = config_data
            config_manager.save_config(config_data)
            
            # 更新元数据
            checksum = self._calculate_checksum(file_path)
            metadata.checksum = checksum
            self.metadata_manager.update_config(metadata)
            
            logger.info(f"保存配置文件成功: {metadata.file_name} (ID: {file_id})")
            return True
            
        except Exception as e:
            logger.error(f"保存配置文件失败: {str(e)}")
            return False
    
    def delete_config(self, file_id: str, delete_file: bool = True) -> bool:
        """
        删除配置文件
        
        Args:
            file_id: 文件ID
            delete_file: 是否同时删除物理文件
            
        Returns:
            bool: 删除是否成功
        """
        try:
            # 获取元数据
            metadata = self.metadata_manager.get_config(file_id)
            if not metadata:
                logger.warning(f"配置文件ID不存在: {file_id}")
                return False
            
            # 构建文件路径
            file_path = os.path.join(self.base_dir, metadata.file_name)
            
            # 删除物理文件
            if delete_file and os.path.exists(file_path):
                os.remove(file_path)
                logger.info(f"删除配置文件: {file_path}")
            
            # 删除元数据
            success = self.metadata_manager.delete_config(file_id)
            if success:
                logger.info(f"删除配置元数据成功: {file_id}")
            
            return success
            
        except Exception as e:
            logger.error(f"删除配置文件失败: {str(e)}")
            return False
    
    def list_configs(self, tags: Optional[List[str]] = None) -> List[Dict[str, Any]]:
        """
        列出所有配置文件
        
        Args:
            tags: 标签列表，用于筛选配置文件
            
        Returns:
            List[Dict[str, Any]]: 配置文件元数据列表
        """
        try:
            metadata_list = self.metadata_manager.list_configs(tags)
            return [metadata.to_dict() for metadata in metadata_list]
            
        except Exception as e:
            logger.error(f"列出配置文件失败: {str(e)}")
            return []
    
    def get_config_details(self, file_id: str) -> Optional[Dict[str, Any]]:
        """
        获取配置文件详细信息
        
        Args:
            file_id: 文件ID
            
        Returns:
            Optional[Dict[str, Any]]: 配置文件详细信息或None
        """
        try:
            metadata = self.metadata_manager.get_config(file_id)
            if not metadata:
                return None
            
            return metadata.to_dict()
            
        except Exception as e:
            logger.error(f"获取配置文件详情失败: {str(e)}")
            return None
    
    def update_config_details(self, 
                             file_id: str, 
                             description: Optional[str] = None, 
                             tags: Optional[List[str]] = None) -> bool:
        """
        更新配置文件元数据
        
        Args:
            file_id: 文件ID
            description: 文件描述
            tags: 标签列表
            
        Returns:
            bool: 更新是否成功
        """
        try:
            metadata = self.metadata_manager.get_config(file_id)
            if not metadata:
                logger.warning(f"配置文件ID不存在: {file_id}")
                return False
            
            # 更新元数据
            if description is not None:
                metadata.description = description
            
            if tags is not None:
                metadata.tags = tags
            
            return self.metadata_manager.update_config(metadata)
            
        except Exception as e:
            logger.error(f"更新配置文件详情失败: {str(e)}")
            return False
    
    def reencrypt_config(self, file_id: str, new_key: Optional[bytes] = None) -> bool:
        """
        使用新密钥重新加密配置文件
        
        Args:
            file_id: 文件ID
            new_key: 新密钥，默认使用SystemKeychain.get_master_key()
            
        Returns:
            bool: 重新加密是否成功
        """
        try:
            # 获取元数据
            metadata = self.metadata_manager.get_config(file_id)
            if not metadata:
                logger.warning(f"配置文件ID不存在: {file_id}")
                return False
            
            # 构建文件路径
            file_path = os.path.join(self.base_dir, metadata.file_name)
            
            # 检查文件是否存在
            if not os.path.exists(file_path):
                logger.warning(f"配置文件不存在: {file_path}")
                return False
            
            # 加载配置
            config_manager = SecureConfigManager(file_path)
            config_data = config_manager.config
            
            # 获取当前密钥和新密钥
            current_key = SystemKeychain.get_master_key()
            new_key = new_key or current_key
            
            # 创建加密器
            old_encryptor = EnhancedAES256Encryptor(current_key)
            new_encryptor = EnhancedAES256Encryptor(new_key)
            
            # 重新加密所有配置项
            reencrypted_config = {}
            for section_name, encrypted_data in config_data.items():
                try:
                    # 解密数据
                    decrypted = old_encryptor.decrypt(encrypted_data)
                    
                    # 使用新密钥重新加密
                    reencrypted = new_encryptor.encrypt(decrypted)
                    
                    # 添加到重新加密的配置中
                    reencrypted_config[section_name] = reencrypted
                    
                except Exception as e:
                    logger.error(f"重新加密配置项失败: {section_name}, {str(e)}")
                    return False
            
            # 保存重新加密的配置
            config_manager.config = reencrypted_config
            config_manager.save_config(reencrypted_config)
            
            # 更新元数据
            checksum = self._calculate_checksum(file_path)
            metadata.checksum = checksum
            metadata.key_id = SystemKeychain.get_key_from_environment()
            self.metadata_manager.update_config(metadata)
            
            logger.info(f"重新加密配置文件成功: {metadata.file_name} (ID: {file_id})")
            return True
            
        except Exception as e:
            logger.error(f"重新加密配置文件失败: {str(e)}")
            return False
    
    def _calculate_checksum(self, file_path: str) -> str:
        """计算文件校验和"""
        if not os.path.exists(file_path):
            return ""
            
        with open(file_path, 'rb') as f:
            file_data = f.read()
            return hashlib.sha256(file_data).hexdigest()
    
    def reencrypt_all_configs(self, old_key: bytes, new_key: bytes) -> Tuple[bool, List[str]]:
        """
        使用新密钥重新加密所有配置文件
        
        Args:
            old_key: 旧密钥
            new_key: 新密钥
            
        Returns:
            Tuple[bool, List[str]]: (是否全部成功, 失败的文件ID列表)
        """
        all_success = True
        failed_files = []
        
        # 获取所有配置文件
        metadata_list = self.metadata_manager.list_configs()
        
        for metadata in metadata_list:
            file_id = metadata.file_id
            file_path = os.path.join(self.base_dir, metadata.file_name)
            
            try:
                if not os.path.exists(file_path):
                    logger.warning(f"配置文件不存在: {file_path}")
                    failed_files.append(file_id)
                    all_success = False
                    continue
                
                # 加载配置
                config_manager = SecureConfigManager(file_path)
                config_data = config_manager.config
                
                # 创建加密器
                old_encryptor = EnhancedAES256Encryptor(old_key)
                new_encryptor = EnhancedAES256Encryptor(new_key)
                
                # 重新加密所有配置项
                reencrypted_config = {}
                for section_name, encrypted_data in config_data.items():
                    try:
                        # 解密数据
                        decrypted = old_encryptor.decrypt(encrypted_data)
                        
                        # 使用新密钥重新加密
                        reencrypted = new_encryptor.encrypt(decrypted)
                        
                        # 添加到重新加密的配置中
                        reencrypted_config[section_name] = reencrypted
                        
                    except Exception as e:
                        logger.error(f"重新加密配置项失败: {section_name}, {str(e)}")
                        failed_files.append(file_id)
                        all_success = False
                        continue
                
                # 保存重新加密的配置
                config_manager.config = reencrypted_config
                config_manager.save_config(reencrypted_config)
                
                # 更新元数据
                checksum = self._calculate_checksum(file_path)
                metadata.checksum = checksum
                metadata.key_id = SystemKeychain.get_key_from_environment()
                self.metadata_manager.update_config(metadata)
                
                logger.info(f"重新加密配置文件成功: {metadata.file_name} (ID: {file_id})")
                
            except Exception as e:
                logger.error(f"重新加密配置文件失败: {file_id}, {str(e)}")
                failed_files.append(file_id)
                all_success = False
        
        return all_success, failed_files 